package com.dean.ui.panel.impl;

import cn.hutool.core.util.StrUtil;
import com.dean.action.CsvOptAction;
import com.dean.constants.DeanUiConstants;
import com.dean.entity.DeanImportInfo;
import com.dean.entity.DeanResponse;
import com.dean.entity.SysDbConnInfo;
import com.dean.service.DbConnService;
import com.dean.ui.panel.DeanPanel;
import com.dean.ui.utils.UiUtils;
import com.dean.utils.PropertyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.time.LocalDateTime;
import java.util.Properties;

/**
 * @ClassName CsvImpExpPanel
 * @Description csv 导入面板
 * @Author dean
 * @Date 2021/10/3 10:03
 */
public class CsvImpExpPanel extends BasePanel implements DeanPanel {

    private static final Logger logger = LoggerFactory.getLogger(CsvImpExpPanel.class);

    /**
     * 配置文件名称
     */
    private final String INIT_PATH_NAME = DeanUiConstants.INIT_PATH + "csv.properties";
    private JLabel connNameLable;
    private JTextArea fieldInput;
    private JTextArea exeLog;
    private JTextField executeRes;
    private JComboBox<String> connName;

    private JLabel commitNumLabel;
    private JTextField commitNum;

    private JLabel speLabel;
    private JTextField separator;

    private JLabel tableNameLabel;
    private JTextField tableName;
    private JButton saveCfgBtn;
    private JLabel inputFilePathLable;
    private JTextField inputFilePath;
    private JScrollPane sqlInput;
    private JScrollPane exeLogPane;

    private JButton exportBtn;
    private JButton importBtn;

    @Override
    public void mainUi() {
        int startRow = 1;
        connNameLable = new JLabel("connName:");
        UiUtils.setRightBounds(connNameLable,startRow);
        panel.add(connNameLable);

        connName = new JComboBox<String>();
        UiUtils.setRightBounds(connName,startRow);
        panel.add(connName);

        // sql输入窗口
        fieldInput = new JTextArea();
        fieldInput.setEditable(true);
        sqlInput = new JScrollPane(fieldInput);
        UiUtils.setTextAreaBounds(sqlInput,startRow,6,1);
        UiUtils.setTextAreaBounds(sqlInput,startRow,6,1);
        panel.add(sqlInput);

        startRow++;

        //文件地址
        inputFilePathLable = new JLabel("请输入文件路径:");
        UiUtils.setRightBounds(inputFilePathLable,startRow);
        panel.add(inputFilePathLable);

        inputFilePath = new JTextField();
        UiUtils.setRightBounds(inputFilePath,startRow);
        panel.add(inputFilePath);
        startRow++;

        //文件地址
        tableNameLabel = new JLabel("TABLENAME:");
        UiUtils.setRightBounds(tableNameLabel,startRow);
        panel.add(tableNameLabel);

        tableName = new JTextField();
        UiUtils.setRightBounds(tableName,startRow);
        panel.add(tableName);
        startRow++;

        speLabel = new JLabel("分割符:");
        UiUtils.setRightBounds(speLabel,startRow);
        panel.add(speLabel);

        separator = new JTextField(",");
        UiUtils.setRightBounds(separator,startRow);
        panel.add(separator);
        startRow++;

        commitNumLabel = new JLabel("commitNum:");
        UiUtils.setRightBounds(commitNumLabel,startRow);
        panel.add(commitNumLabel);

        commitNum = new JTextField("4000");
        UiUtils.setRightBounds(commitNum,startRow);
        panel.add(commitNum);
        startRow++;


        saveCfgBtn = new JButton("保存配置信息");
        UiUtils.setRightButtonBounds(saveCfgBtn,startRow,1);
        panel.add(saveCfgBtn);

        exportBtn = new JButton("导出CSV");
        UiUtils.setRightButtonBounds(exportBtn,startRow,2);
        panel.add(exportBtn);

        // 执行按钮
        importBtn = new JButton("导入CSV");
        UiUtils.setRightButtonBounds(importBtn,startRow,3);
        panel.add(importBtn);
        startRow++;

        // 查询列表窗口
        exeLog = new JTextArea();
        exeLogPane = new JScrollPane(exeLog);
        exeLog.setEnabled(false);
        exeLog.setText("使用说明:\n" +
                "1.csv或者txt文件导入 \n" +
                "1.1 如果不指定字段的列名则需要文件中有表头信息（默认为文件的第一行如果在其他行需要指定表头行） \n" +
                "1.2 如果指定了表头则按照文件的字段顺序赋值有多余的列会忽略不计\n" +
                "1.2 注意建表时需要创建remark字段,程序会将文件名称存入remark字段 \n" +
                "1.3 指定的文件目录下不要存放多余的csv或者txt文件否则会默认进行文件导入导致错误数据入库 \n" +
                "1,4 每次提交的记录数请根据服务的实际情况调整 \n" +
                "1.5 导入时需要指定导入的表名 \n" +
                "2.csv或者txt导出 \n" +
                "2.1 需要输入sql语句用【;】进行sql语句分割 \n" +
                "2.2 指定导出的文件路径 \n" +
                "2.3 如果需要指定对应sql导出的文件名称可以参考如下配置: \n" +
                "    select * from tb_user ### user_list.csv \n" +
                "2.4 如果不指定文件名称则采用uuid 命名 \n" +
                "2.5 导出是并发执行的，如果需要知道哪些文件导出请查看日志 \n" +
                "2.6 导入如果没有特殊情况，导出的分隔符默认为【,】");

        UiUtils.setTextAreaBounds(exeLogPane,startRow,-1,1,2);
        UiUtils.setTextAreaBounds(exeLog,startRow,-1,1,2);

        panel.add(exeLogPane);


    }

    @Override
    public void mainScript() {
        // 下拉框处理
        DbConnService.getInstance().getConnInfos().forEach(connInfo -> {
            connName.addItem(connInfo.getConnName());
        });
        connName.addItemListener(new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                if (e.getStateChange() == ItemEvent.SELECTED) {
                    String connNameSelected = e.getItem().toString();
                    logger.debug("当前选中了{}", connNameSelected);
                }
            }
        });

        saveCfgBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (saveProperties()) {
                    JOptionPane.showMessageDialog(panel, "配置信息保存成功", "SUCESS", JOptionPane.INFORMATION_MESSAGE);
                } else {
                    JOptionPane.showMessageDialog(panel, "配置信息保存失败", "ERROR", JOptionPane.ERROR_MESSAGE);
                }
            }
        });

        exportBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                csvExp();
            }
        });

        importBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                csvImp();
            }
        });

    }

    private void csvExp() {

        String filePath = inputFilePath.getText();
        if (filePath == null || filePath == "") {
            JOptionPane.showMessageDialog(panel, "请输入文件导出目录", "ERROR", JOptionPane.ERROR_MESSAGE);
            return;
        }

        String exeSql = fieldInput.getText();
        if (exeSql == null || "".equals(exeSql)) {
            JOptionPane.showMessageDialog(panel, "执行sql不能为空", "ERROR", JOptionPane.ERROR_MESSAGE);
            return;
        }
        if (!exeSql.trim().toLowerCase().startsWith(DeanUiConstants.START_SELECT_CHAR)) {
            JOptionPane.showMessageDialog(panel, "非法sql，不允许执行", "ERROR", JOptionPane.ERROR_MESSAGE);
            return;
        }
        String[] exeSqls = exeSql.replaceAll("\n", "").split(";");
        logger.debug("执行开始时间:" + LocalDateTime.now());
        CsvOptAction optAction = CsvOptAction.getInstance();
        DeanResponse deanResponse = optAction.exportCsv(initDbConnect(),filePath,exeSqls,separator.getText());
        if(deanResponse.getCode() == 0){
            JOptionPane.showMessageDialog(panel, deanResponse.getMsg(), "SUCCESS", JOptionPane.INFORMATION_MESSAGE);
        }else{
            JOptionPane.showMessageDialog(panel, deanResponse.getMsg(), "ERROR", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void csvImp() {
        // 获取执行参数
        String exeParams = fieldInput.getText();
        String[] fields = new String[0];
        if(StrUtil.isNotBlank(exeParams)){
            fields = exeParams.split(",");
        }

        String filePath = inputFilePath.getText();
        if(filePath == null || "".equals(filePath)){
            JOptionPane.showMessageDialog(panel, "导入文件地址不能为空", "ERROR", JOptionPane.ERROR_MESSAGE);
            return;
        }
        CsvOptAction csvOptAction = CsvOptAction.getInstance();
        DeanResponse deanResponse = csvOptAction.importCsv(initDbConnect(),filePath, initImportInfo(fields));
        if(deanResponse.getCode() == 0){
            JOptionPane.showMessageDialog(panel, deanResponse.getMsg(), "SUCCESS", JOptionPane.INFORMATION_MESSAGE);
        }else{
            JOptionPane.showMessageDialog(panel, deanResponse.getMsg(), "ERROR", JOptionPane.ERROR_MESSAGE);
        }
        logger.debug("csv文件导入结束,导入结束时间:{}", LocalDateTime.now());
    }

    /**
     * 保存配置文件
     *
     * @return
     */
    private boolean saveProperties() {
        Properties properties = new Properties();
        // 读取 接口地址 db_driver db_url db_username db_password
        properties.setProperty("connName", connName.getSelectedItem().toString());
        properties.setProperty("commitNum", commitNum.getText());
        properties.setProperty("tmp_tablename", tableName.getText());
        properties.setProperty("inputFilePath", inputFilePath.getText());
        properties.setProperty("field_input", fieldInput.getText());
        properties.setProperty("separator", separator.getText());
        return PropertyUtils.saveProperties(INIT_PATH_NAME, properties);
    }

    @Override
    public void initProperties() {
        //初始化基础参数
        Properties properties = PropertyUtils.readProperties(INIT_PATH_NAME);
        if (properties != null) {
            connName.setSelectedItem(properties.getProperty("connName"));
            commitNum.setText(properties.getProperty("commitNum"));
            tableName.setText(properties.getProperty("tmp_tablename"));
            inputFilePath.setText(properties.getProperty("inputFilePath"));
            fieldInput.setText(properties.getProperty("field_input"));
            separator.setText(properties.getProperty("separator"));
        }
    }

    /**
     * 设置数据库连接配置
     */
    private SysDbConnInfo initDbConnect() {
        SysDbConnInfo connectInfo = new SysDbConnInfo();
        connectInfo.setConnName(connName.getSelectedItem().toString());
        return connectInfo;
    }


    /**
     * 导入需要的信息
     * @param fields
     * @return
     */
    private DeanImportInfo initImportInfo(String [] fields){
        DeanImportInfo importInfo = new DeanImportInfo();
        importInfo.setFields(fields);
        importInfo.setTableName(tableName.getText());
        importInfo.setCommitNums(Integer.parseInt(commitNum.getText()));
        importInfo.setDelimiter(separator.getText());
        return importInfo;
    }

}
